#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <openssl/rsa.h>       /* SSLeay stuff */
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "se_ssl.h"

/* define HOME to be dir for key and cert files... */
#define HOME "/home/web/cert/certs/"
/* Make these what you want for cert & key files */
#define CERTF  HOME "ssltest.cert.pem"
#define KEYF  HOME  "ssltest.key.pem"


#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }

static void _set_fd_nonblock(int fd)
{
    int flag = fcntl(fd,F_GETFL,0);
    if(-1 == flag)
    {
	printf("%s,fail to get fd flag:%s\n",__FUNCTION__,strerror(errno));
	return;
    }

    if(-1 == fcntl(fd,F_SETFL,flag|O_NONBLOCK))
    {
	printf("%s,fail to set fd nonblock:%s\n",__FUNCTION__,strerror(errno));
    }
}

void main ()
{
  int err;
  int listen_sd;
  int sd;
  struct sockaddr_in sa_serv;
  struct sockaddr_in sa_cli;
  size_t client_len;
  //SSL_CTX* ctx;
  //SSL*     ssl;
  void* rwBio=NULL;
  X509*    client_cert;
  char*    str;
  char     buf [4096];
  SE_TLS_CTX_S se_tls_ctx;
  //SSL_METHOD *meth;
  
  /* SSL preliminaries. We keep the certificate and key with the context. */
	SE_tls_init();
   
  /* ----------------------------------------------- */
  /* Prepare TCP socket for receiving connections */

  listen_sd = socket (AF_INET, SOCK_STREAM, 0);   CHK_ERR(listen_sd, "socket");
  
  memset (&sa_serv, '\0', sizeof(sa_serv));
  sa_serv.sin_family      = AF_INET;
  sa_serv.sin_addr.s_addr = INADDR_ANY;
  sa_serv.sin_port        = htons (1111);          /* Server Port number */
  
  err = bind(listen_sd, (struct sockaddr*) &sa_serv,
	     sizeof(sa_serv));                    CHK_ERR(err, "bind");
	     
  /* Receive a TCP connection. */
	     
  err = listen (listen_sd, 5);                    CHK_ERR(err, "listen");
  
  client_len = sizeof(sa_cli);
  sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
  CHK_ERR(sd, "accept");
  close (listen_sd);
_set_fd_nonblock(sd);
  printf ("Connection from %lx, port %x\n",
	  sa_cli.sin_addr.s_addr, sa_cli.sin_port);
  
  /* ----------------------------------------------- */
  /* TCP connection is ready. Do server side SSL. */


  /* DATA EXCHANGE - Receive message and send reply. */

    //rwBio = SE_tls_new(sd,0,CERTF,KEYF);
	SE_init_tlsctx(&se_tls_ctx,sd,0);
	SE_setTlsCtxCert(&se_tls_ctx,"/home/web/cert/certs/ssltest.cert.pem","/home/web/cert/certs/ssltest.key.pem");
	err= SE_tls_new(&se_tls_ctx,&rwBio);
	if (err != SE_TLS_SUCCESS && err != SE_TLS_TCP_ONLY )
	{
		printf("tls new failed\n");
		return;
	}
  err = SE_tls_read (rwBio, buf, sizeof(buf) - 1);                   CHK_SSL(err);
  buf[err] = '\0';
  printf ("Got %d chars:'%s'\n", err, buf);
  
  err = SE_tls_write (rwBio, "I hear you.", strlen("I hear you."));  CHK_SSL(err);

  /* Clean up. */
	SE_tls_delete(rwBio);
  close (sd);
  //SSL_free (ssl);
  //SSL_CTX_free (ctx);
}
